home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 February: Tool Chest / Dev.CD Feb 95 / Dev.CD Feb 95.toast / Tool Chest / Development Tools & Languages / Dylan Related / Mindy-1.1 (sources only) / mindy-1.1 / interp / print.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-18  |  6.6 KB  |  293 lines  |  [TEXT/ttxt]

  1. /**********************************************************************\
  2. *
  3. *  Copyright (c) 1994  Carnegie Mellon University
  4. *  All rights reserved.
  5. *  
  6. *  Use and copying of this software and preparation of derivative
  7. *  works based on this software are permitted, including commercial
  8. *  use, provided that the following conditions are observed:
  9. *  
  10. *  1. This copyright notice must be retained in full on any copies
  11. *     and on appropriate parts of any derivative works.
  12. *  2. Documentation (paper or online) accompanying any system that
  13. *     incorporates this software, or any part of it, must acknowledge
  14. *     the contribution of the Gwydion Project at Carnegie Mellon
  15. *     University.
  16. *  
  17. *  This software is made available "as is".  Neither the authors nor
  18. *  Carnegie Mellon University make any warranty about the software,
  19. *  its performance, or its conformity to any specification.
  20. *  
  21. *  Bug reports, questions, comments, and suggestions should be sent by
  22. *  E-mail to the Internet address "gwydion-bugs@cs.cmu.edu".
  23. *
  24. ***********************************************************************
  25. *
  26. * $Header: print.c,v 1.8 94/08/02 15:06:50 dpierce Exp $
  27. *
  28. * This file implements the printer framework.
  29. *
  30. \**********************************************************************/
  31.  
  32. #include <stdarg.h>
  33. #include <stdio.h>
  34.  
  35. #include "mindy.h"
  36. #include "obj.h"
  37. #include "class.h"
  38. #include "bool.h"
  39. #include "list.h"
  40. #include "print.h"
  41. #include "vec.h"
  42. #include "char.h"
  43. #include "str.h"
  44. #include "thread.h"
  45. #include "func.h"
  46. #include "def.h"
  47. #include "sym.h"
  48. #include "error.h"
  49. #include "num.h"
  50. #include "type.h"
  51.  
  52. void def_printer(obj_t class, void (*print_fn)(obj_t object))
  53. {
  54.     obj_ptr(struct class *, class)->print = print_fn;
  55. }
  56.  
  57. static int depth = 0;
  58.  
  59. void prin1(obj_t object)
  60. {
  61.     obj_t class = object_class(object);
  62.     obj_t cpl = obj_ptr(struct class *, class)->cpl;
  63.     obj_t debug_name;
  64.  
  65.     if (depth > 10) {
  66.     putchar('#');
  67.     return;
  68.     }
  69.  
  70.     depth++;
  71.  
  72.     if (cpl) {
  73.     while (cpl != obj_Nil) {
  74.         void (*print_fn)(obj_t object)
  75.         = obj_ptr(struct class *, HEAD(cpl))->print;
  76.  
  77.         if (print_fn != NULL) {
  78.         print_fn(object);
  79.         depth--;
  80.         return;
  81.         }
  82.  
  83.         cpl = TAIL(cpl);
  84.     }
  85.     }
  86.  
  87.     debug_name = obj_ptr(struct class *, class)->debug_name;
  88.     if (debug_name != NULL && debug_name != obj_False)
  89.     printf("{%s 0x%08lx}", sym_name(debug_name), (unsigned long)object);
  90.     else
  91.     printf("{0x%08lx}", (unsigned long)object);
  92.  
  93.     depth--;
  94. }
  95.  
  96. void print(obj_t object)
  97. {
  98.     prin1(object);
  99.     putchar('\n');
  100. }
  101.  
  102. void format(char *fmt, ...)
  103. {
  104.     int args = count_format_args(fmt);
  105.     obj_t vec = make_vector(args, NULL);
  106.     int i;
  107.     va_list ap;
  108.  
  109.     va_start(ap, fmt);
  110.     for (i = 0; i < args; i++)
  111.     SOVEC(vec)->contents[i] = va_arg(ap, obj_t);
  112.     va_end(ap);
  113.  
  114.     vformat(fmt, SOVEC(vec)->contents);
  115. }
  116.  
  117. int count_format_args(char *fmt)
  118. {
  119.     char *ptr;
  120.     int args = 0;
  121.  
  122.     for (ptr = fmt; *ptr != '\0'; ptr++) {
  123.     if (*ptr == '%') {
  124.         switch (*++ptr) {
  125.               case 'd': case 'D':
  126.           case 'b': case 'B':
  127.           case 'o': case 'O':
  128.           case 'x': case 'X':
  129.           case 'c': case 'C':
  130.           case 's': case 'S':
  131.           case '=':
  132.         args++;
  133.         break;
  134.           case '%':
  135.         break;
  136.           default:
  137.         error("Unknown format directive in error msg: %%%c", 
  138.               int_char(*ptr));
  139.         }
  140.     }
  141.     }
  142.  
  143.     return args;
  144. }
  145.  
  146. /* Works only for numbers greater than 0. If zero, prints nothing. */
  147.  
  148. void print_nonzero_in_binary(int number)
  149. {
  150.     if (number != 0) {
  151.     print_nonzero_in_binary(number >> 1);
  152.     fputc('0' + (number & 1), stdout);  /* Extract the low bit 
  153.                                                and convert to ASCII */
  154.     }
  155. }
  156.  
  157. void print_number_in_binary(int number)
  158. {
  159.     if (number == 0)
  160.     fputc('0', stdout);
  161.     else
  162.     print_nonzero_in_binary(number);
  163. }
  164.  
  165.  
  166. void vformat(char *fmt, obj_t *args)
  167. {
  168.     while (*fmt != '\0') {
  169.     if (*fmt == '%') {
  170.         switch (*++fmt) {
  171.               case 'd':
  172.           case 'D':
  173.         check_type(*args, obj_IntegerClass);
  174.         fprintf(stdout, "%ld", fixnum_value(*args++));
  175.         break;
  176.               case 'b':
  177.           case 'B':
  178.         check_type(*args, obj_IntegerClass);
  179.         print_number_in_binary(fixnum_value(*args++));
  180.         break;
  181.               case 'o':
  182.           case 'O':
  183.         check_type(*args, obj_IntegerClass);
  184.         fprintf(stdout, "%lo", fixnum_value(*args++));
  185.         break;
  186.               case 'x':
  187.           case 'X':
  188.         check_type(*args, obj_IntegerClass);
  189.         fprintf(stdout, "%lx", fixnum_value(*args++));
  190.         break;
  191.           case 'c':
  192.           case 'C':
  193.         check_type(*args, obj_CharacterClass);
  194.         fputc(char_int(*args++), stdout);
  195.         break;
  196.           case '=':
  197.         prin1(*args++);
  198.         break;
  199.           case 's':
  200.           case 'S':
  201.         /* Gotta somehow have two cases,          */
  202.         /* one for strings and another for errors */
  203.         if (instancep(*args, obj_ByteStringClass)) {
  204.           fputs(string_chars(*args++), stdout);
  205.         }
  206. /* This will have to be commented out until we figure out how 
  207.    to print conditions. */
  208. /*        else if (instancep(*args, obj_ConditionClass)) {
  209.           fputs(conditionthing, *args++);
  210.         }
  211. */
  212.         else {
  213.           error("%= is neither a string nor a condition,"
  214.             " and so can't be printed with %%s", *args++);
  215.         }
  216.         break;
  217.           case '%':
  218.         putchar('%');
  219.         break;
  220.           default:
  221.         error("Unknown format directive in error msg: %%%c", 
  222.               int_char(*fmt));
  223.           }
  224.     }
  225.     else
  226.         putchar(*fmt);
  227.     fmt++;
  228.     }
  229. }
  230.  
  231.  
  232. /* Dylan routines */
  233.  
  234. static obj_t dylan_print(obj_t obj)
  235. {
  236.     print(obj);
  237.     return obj;
  238. }
  239.  
  240. static obj_t dylan_prin1(obj_t obj)
  241. {
  242.     prin1(obj);
  243.     return obj;
  244. }
  245.  
  246. static obj_t dylan_putc(obj_t obj)
  247. {
  248.     putchar(char_int(obj));
  249.     return obj;
  250. }
  251.  
  252. static obj_t dylan_puts(obj_t obj)
  253. {
  254.     fputs(string_chars(obj), stdout);
  255.     return obj;
  256. }
  257.  
  258. static void dylan_format(struct thread *thread, int nargs)
  259. {
  260.     obj_t *args = thread->sp - nargs;
  261.     obj_t *old_sp;
  262.     obj_t fmt = args[0];
  263.  
  264.     push_linkage(thread, args);
  265.  
  266.     check_type(fmt, obj_ByteStringClass);
  267.  
  268.     vformat(string_chars(fmt), args+1);
  269.  
  270.     old_sp = pop_linkage(thread);
  271.     thread->sp = old_sp;
  272.  
  273.     do_return(thread, old_sp, old_sp);
  274. }
  275.  
  276.  
  277. /* Init stuff. */
  278.  
  279. void init_print_functions(void)
  280. {
  281.     define_function("print", list1(obj_ObjectClass), FALSE, obj_False, FALSE,
  282.             obj_ObjectClass, dylan_print);
  283.     define_function("prin1", list1(obj_ObjectClass), FALSE, obj_False, FALSE,
  284.             obj_ObjectClass, dylan_prin1);
  285.     define_function("putc", list1(obj_CharacterClass), FALSE, obj_False, FALSE,
  286.             obj_CharacterClass, dylan_putc);
  287.     define_function("puts", list1(obj_ByteStringClass), FALSE, obj_False,
  288.             FALSE, obj_ByteStringClass, dylan_puts);
  289.     define_constant("format",
  290.             make_raw_function("format", 1, TRUE, obj_False, FALSE,
  291.                       obj_Nil, obj_False, dylan_format));
  292. }
  293.